package com.gitee.wsl.concurrent.executor.sample

import com.gitee.wsl.concurrent.executor.Executor
import kotlinx.coroutines.CoroutineDispatcher
import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.InternalCoroutinesApi
import kotlinx.coroutines.Runnable
import kotlinx.coroutines.SupervisorJob
import kotlinx.coroutines.cancel
import kotlinx.coroutines.internal.SynchronizedObject
import kotlinx.coroutines.internal.synchronized
import kotlinx.coroutines.isActive
import kotlinx.coroutines.launch

fun Executor.Companion.fromDispatcher(dispatcher: CoroutineDispatcher) = DispatcherExecutor(dispatcher)

fun CoroutineDispatcher.toExecutor() = DispatcherExecutor(this)

class DispatcherExecutor(
    dispatcher: CoroutineDispatcher
) : Executor {

    @OptIn(InternalCoroutinesApi::class)
    private val lock = SynchronizedObject()
    private val scope = CoroutineScope(dispatcher + SupervisorJob())

    override val isDisposed: Boolean
             get() = scope.isActive

    @OptIn(InternalCoroutinesApi::class)
    override fun exec(runnable: Runnable):Unit = synchronized(lock) {
            scope.launch { runnable.run() }
        }

    @OptIn(InternalCoroutinesApi::class)
    override fun dispose() {
        synchronized(lock) {
            scope.cancel()
        }
    }
}